package com.kool.kauth.common.exception;

import com.kool.kauth.common.constant.ErrorCode;
import com.kool.kauth.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;

/**
 * @DESCRIBE 程序异常，在请求返回前抓取
 * @AUTHOR LUYU
 * @DATE 2017-04-26 22:43:35
 */
@Slf4j
public class AppException extends RuntimeException {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    /**
     * 错误码
     */
    private Integer errCod;
    /**
     * 错误信息
     */
    private String errMsg;
    /**
     * 抓取的AppException异常栈，不包括自身
     */
    private ArrayList<AppException> listAE;

    public AppException(Integer errCod) {
        this.errCod = errCod;
        this.errMsg = translate(errCod, null);
    }

    public AppException(ErrorCode errCod) {
        this.errCod = errCod.getCode();
        this.errMsg = translate(errCod.getCode(), null);
    }

    public AppException(Integer errCod, String... args) {
        this.errCod = errCod;
        this.errMsg = translate(errCod, args);
    }

    public AppException(ErrorCode errCod, String... args) {
        this.errCod = errCod.getCode();
        this.errMsg = translate(errCod.getCode(), args);
    }

    /**
     * 如果是抓取异常后构造AppException异常，则需要传入被抓取的异常，以此保证异常信息的完整
     *
     * @param errCod
     * @param e
     */
    public AppException(Integer errCod, Exception e) {
        log.error(e.getMessage(),e);
        this.setStackTrace(e.getStackTrace());
        this.errCod = errCod;
        this.errMsg = translate(errCod, null);

        if (e instanceof AppException) {
            listAE = new ArrayList<>();
            AppException e2 = (AppException) e;
            if (e2.getListAE() != null) {
                listAE.addAll(e2.getListAE());
            }
            listAE.add(e2);
        }
    }

    public AppException(ErrorCode errCod, Exception e) {
        log.error(e.getMessage(),e);
        this.setStackTrace(e.getStackTrace());
        this.errCod = errCod.getCode();
        this.errMsg = translate(errCod.getCode(), null);

        if (e instanceof AppException) {
            listAE = new ArrayList<>();
            AppException e2 = (AppException) e;
            if (e2.getListAE() != null) {
                listAE.addAll(e2.getListAE());
            }
            listAE.add(e2);
        }
    }

    public AppException(Integer errCod, Exception e, String... args) {
        log.error(e.getMessage(),e);
        this.setStackTrace(e.getStackTrace());
        this.errCod = errCod;
        this.errMsg = translate(errCod, args);

        if (e instanceof AppException) {
            listAE = new ArrayList<>();
            AppException e2 = (AppException) e;
            if (e2.getListAE() != null) {
                listAE.addAll(e2.getListAE());
            }
            listAE.add(e2);
        }
    }

    public AppException(ErrorCode errCod, Exception e, String... args) {
        log.error(e.getMessage(),e);
        this.setStackTrace(e.getStackTrace());
        this.errCod = errCod.getCode();
        this.errMsg = translate(errCod.getCode(), args);

        if (e instanceof AppException) {
            listAE = new ArrayList<>();
            AppException e2 = (AppException) e;
            if (e2.getListAE() != null) {
                listAE.addAll(e2.getListAE());
            }
            listAE.add(e2);
        }
    }

    /**
     * @return
     * @DESCRIBE 获取异常信息
     * @DATE 2018年6月30日 下午11:24:12
     */
    @Override
    public String getMessage() {
        StringBuilder msg = new StringBuilder();
        if (errMsg != null) {
            msg.append(errMsg);
        }
        return msg.toString();
    }

    /**
     * @return
     * @DESCRIBE 获取AppException异常栈的所有异常信息, 外层的异常在组数前面
     * @DATE 2018年6月30日 下午11:23:23
     */
    public ArrayList<String> getAllMessages() {
        ArrayList<String> listMsg = new ArrayList<>();
        if (listAE != null) {
            for (AppException ae : listAE) {
                listMsg.add(ae.getMessage());
            }
        }
        listMsg.add(this.getMessage());
        return listMsg;
    }

    /**
     * @return
     * @DESCRIBE 获取异常错误码
     * @DATE 2018年6月20日 下午2:28:00
     */
    public Integer getErrorCode() {
        return this.errCod;
    }

    /**
     * @return
     * @DESCRIBE 获取异常栈
     * @DATE 2018年7月1日 上午12:04:56
     */
    public ArrayList<AppException> getListAE() {
        return this.listAE;
    }

    /**
     * @param errCod
     * @param args
     * @return
     * @DESCRIBE 翻译错误码。根据错误码从缓存中读取错误码信息
     * @DATE 2018年6月30日 下午11:21:32
     */
    private String translate(Integer errCod, String[] args) {
        String msg = ErrorCode.getMsgByCode(errCod);
        if (StringUtil.isNotEmpty(msg)) {
            msg = String.format(msg, args);
        }
        return msg;
    }
}
